package com.eshipenet.shipnet.equipmentextbuilder

import play.api.libs.json.{JsDefined, JsObject, JsString, JsValue, Json}

import scala.util.{Failure, Success, Try}

object EquipmentWithModel {

  def apply(equipment: Equipment, modelSchema: EquipmentModel, link: EquipmentModelLink): EquipmentWithModel =
    new EquipmentWithModel(equipment, modelSchema, link)

}

case class EquipmentWithModel(equipment: Equipment, modelSchema: EquipmentModel, link: EquipmentModelLink) {
  val model: EquipmentModel = generateModel(modelSchema)

  private def generateModel(modelSchema: EquipmentModel): EquipmentModel =
    Try {
      val dataJson = modelSchema.raw \ "data" match {
        case JsDefined(JsString(s)) => Json.parse(s).as[Map[String, JsValue]]
        case JsDefined(x: JsObject) => x.as[Map[String, JsValue]]
        case _                      => throw new Exception("invalid data")
      }
      val data = dataJson.mapValues(v => (v, v.asOpt[JsObject])).map { kv =>
        val value = kv._2
        val newValue = value._2 match {
          case Some(schema) => instantiate(kv._1, schema)
          case _            => value._1
        }
        (kv._1, newValue)
      }
      val raw = modelSchema.raw + ("instData" -> Json.toJson(data))
//      println("raw", modelSchema.copy(raw = raw))
      modelSchema.copy(raw = raw)
    } match {
      case Success(e) => e
      case Failure(exception) =>
        exception.printStackTrace()
        modelSchema
    }

  private def instantiate(key: String, datum: JsObject): JsValue = {
    val edgeChannelId = link.dataBinding.get(key)
    datum + ("edgeChannelId" -> Json.toJson(edgeChannelId))
  }
}
